package com.Cfeng.XiaohuanChat.listener;

import com.Cfeng.XiaohuanChat.entity.ChatMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionConnectedEvent;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;

import javax.annotation.Resource;

/**
 * @author Cfeng
 * @date 2022/8/3
 * websocket的事件监听器，监听用户下线消息
 * 创建的单例对象放入的容器，所以可以直接监听在线用户
 * STOMP的登录和下线都是Session的连接和断开事件，监听这两个事件，就可以获取到当前的在线的用户【principal】
 */

@Component
@Slf4j
public class WebSocketEventListener {
    //消息模板，自动配置的,其实现对象为SimpMessagingTemplate类型
    @Resource
    private SimpMessageSendingOperations messagingTemplate;

    /**
     * 监听事件基于websocket提供的SessionConnectEvent，用户上线连接就会触发spring的此监听的方法
     */
    @EventListener
    public void handleWebSocketConnectLister(SessionConnectedEvent event) {
        log.info(event.getUser().toString()); //Security配合STOMP，event的主体principal就是security登录的principal
        log.info("Received a new web connection");
    }

    /**
     * 让spring监听websocket连接断开事件，表明用户下线，使用模板发送到公共频道
     * 使用StompHeaderAccessor进行消息与帧转换
     */
    @EventListener
    public void handleWebSocketDidConnectLister(SessionDisconnectEvent event) {
        //通过断开事件的消息wrap一个头访问器，为simpXX的子类，可以取出之前的放入的数据
        StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
        //获取session的数据
        String username = (String) headerAccessor.getSessionAttributes().get("username");
        if(username != null) {
            log.info("{} disconnected，下线了",username);
            ChatMessage chatMessage = new ChatMessage().setType(ChatMessage.MessageType.LEAVE).setSender(username).setContent("");
            //通过消息转换器放入STOMP帧，转发给消息代理公共频道
            messagingTemplate.convertAndSend("/topic/public",chatMessage);
        }
    }
}
